package bg.cinema_system.exceptions;

import java.util.Iterator;
import java.util.Map;

import javax.faces.FacesException;
import javax.faces.application.NavigationHandler;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;

public class CustomExceptionHandler extends ExceptionHandlerWrapper {
	private ExceptionHandler exceptionHandler;

	CustomExceptionHandler(ExceptionHandler exceptionHandler) {
		this.exceptionHandler = exceptionHandler;
	}

	@Override
	public ExceptionHandler getWrapped() {
		return this.exceptionHandler;
	}

	@Override
	public void handle() throws FacesException {
		final Iterator<ExceptionQueuedEvent> iterator = getUnhandledExceptionQueuedEvents()
				.iterator();

		while (iterator.hasNext()) {
			ExceptionQueuedEvent exceptionQueuedEvent = iterator.next();
			ExceptionQueuedEventContext exceptionQueuedEventContext = (ExceptionQueuedEventContext) exceptionQueuedEvent
					.getSource();

			// Get the exception from context
			Throwable throwable = exceptionQueuedEventContext.getException();

			final FacesContext facesContext = FacesContext.getCurrentInstance();
			final Map<String, Object> requestMap = facesContext
					.getExternalContext().getRequestMap();
			final NavigationHandler navigationHandler = facesContext
					.getApplication().getNavigationHandler();

			// Handle the exception and work with it
			try {
				// Redirect to an error page
				requestMap.put("exceptionMessage", throwable.getMessage());
				facesContext
						.getExternalContext()
						.getFlash()
						.put("exceptionINFO",
								throwable.getCause() + " "
										+ throwable.getMessage());
				navigationHandler.handleNavigation(facesContext, null,
						"/error?faces-redirect=true");
				facesContext.renderResponse();
			} finally {
				// Remove it from queue
				iterator.remove();
			}
		}

		// Parent handle
		getWrapped().handle();
	}
}
